home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 22 code / PCI Driver Sample / NCR_DriverProject / Src / LogLibrary.h < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-31  |  27.0 KB  |  674 lines  |  [TEXT/MPCC]

  1. /*                                        LogLibrary.h                                */
  2. /*
  3.  * LogLibrary.h
  4.  * Copyright © 1992-95 Apple Computer Inc. All Rights Reserved.
  5.  * Programmed by Martin Minow,
  6.  *    Internet:    minow@apple.com
  7.  *    AppleLink:    MINOW
  8.  * Version of March 31, 1995
  9.  */
  10.  
  11. #ifndef __LogLibrary__
  12. #define __LogLibrary__
  13. /*
  14.  * Usage:
  15.  *    PowerPC (native):
  16.  *        Include "LogLibrary.h" in all compilations.
  17.  *        Either compile the LogLibrary functions or include LogLibrary (shared library).
  18.  *    68000 emulation
  19.  *        Include "LogLibrary.h" in all compilations.
  20.  *        Compile LogLibrary.c, LogConvertTimestamp.c, and LogFormatTimestamp.c
  21.  *        (or include an object).
  22.  *        Make LogLibrary known to the executing program, possibly by storing
  23.  *        it in the Extensions folder.
  24.  *
  25.  * Edit History
  26.  *    94.10.16 MM        Revised (throughly) from the Audit library to take advantage of
  27.  *                    the new I/O architecture. The library name has been changed from
  28.  *                    Audit to DriverLog. The driver log is named through the System
  29.  *                    Name Registry. These functions are (currently) only available in
  30.  *                    PowerPC.
  31.  *    94.12.12 MM        Finished converting to LogLibrary, added Mixed Mode support so
  32.  *                    the (Power PC) library may be called from 68000 code.
  33.  *    95.02.03 MM        • Changed WriteLogEntry, StoreLogEntry, and ReadLogEntry to return
  34.  *                    OSErr's (to distinguish between semaphore interlock and other
  35.  *                    errors). This will allow a non-interrupt application to loop
  36.  *                    while the semaphore is interlocked, though this is not trivial.
  37.  *                    • Removed the StoreString function (now inlined).
  38.  *                    • Removed the lost data counter and entry. Sequence gaps can
  39.  *                    best be determined by watching the atomic sequence counter.
  40.  *                    • Use IncrementAtomic to update the sequence counter. This will
  41.  *                    also count data lost if the semaphore is interlocked.
  42.  *                    • StoreLogEntry stores the sequence counter and timestamp into
  43.  *                    the caller's LogEntryRecord: it is not called with a const
  44.  *                    LogEntryPtr.
  45.  * 95.03.31 MM        Added 68000-callable UpTime, removed UpTime from ReadLogEntry and
  46.  *                    CopyLogRecordEntry. LogConvertTimestamp doesn't need this.
  47.  *
  48.  * Note: because Pascal does not support variable-length calling sequences, the
  49.  * WriteLogEntry function may only be called from C. Pascal programs must format the
  50.  * LogEntryRecord and call StoreLogEntry directly.
  51.  */
  52. /*
  53.  * To create an log library record, a driver, application, or other code segment calls
  54.  * MakeLogRecord(). This is the only function that accesses the memory manager (but
  55.  * see the note on 68000's below). The record is created by the PoolAllocateResident
  56.  * routine and must be called from task level. If the log has already been created, it
  57.  * returns a pointer to that log record.
  58.  *
  59.  * MakeLogRecord() must be called in a context that can allocate memory. The first
  60.  * call from a 68000 architecture module must be able to load a shared library.
  61.  *
  62.  * To log data, call the WriteLogEntry() routine, normally using one of the formatting
  63.  * macros.
  64.  *
  65.  * To read the next entry from the log, call the ReadLogEntry() routine.
  66.  *
  67.  * Once created, a log persists until system restart. The problem is that many
  68.  * routines might have grabbed the log address from the name registry, so deleting
  69.  * it from the registry is insufficient.
  70.  *
  71.  * There are a few other routines, but they aren't that important.
  72.  *
  73.  * A reader application processes log entries as follows.
  74.  *
  75.  *         Str255                timeText, dataText;
  76.  *        LogRecordPtr        logRecordPtr;
  77.  *        LogEntryPtr            logEntryPtr;
  78.  *        DateTimeRec            eventTime;
  79.  *        UInt32                nanoseconds;
  80.  * 
  81.  *        MyOpenLogOutputFile();
  82.  *        logPtr = GetLogRecordPtr("MyLogRecord");
  83.  *        if (logPtr != NULL) {
  84.  *            while (gQuitNow == FALSE) {
  85.  *                ProcessOneEvent();
  86.  *                for (i = 0; i < 10; i++) {
  87.  *                    if (ReadLogEntry(logPtr, &logEntry) != noErr)
  88.  *                        break;
  89.  *                    else {
  90.  *                        ConvertLogEntryTimestamp(&logEntry, &eventTime, &nanoseconds);
  91.  *                        FormatLogEntryTimestamp(timeText, &eventTime, nanoseconds);
  92.  *                        FormatLogEntryData(&logEntry, dataText);
  93.  *                        printf("%.*s: %.*s\n",
  94.  *                            timeText[0], &timeText[1],
  95.  *                            dataText[0], &dataText[1]
  96.  *                        );
  97.  *                    }
  98.  *                }
  99.  *            }
  100.  *        }
  101.  *        ExitToShell();
  102.  */
  103.  
  104. #ifndef SystemSevenOrLater
  105. #define SystemSevenOrLater    1
  106. #endif
  107.  
  108. #include <stdarg.h>
  109. #ifndef THINK_C /* Temp until headers stabalize */
  110. #include <MixedMode.h>
  111. #include <Types.h>
  112. #include <OSUtils.h>
  113. #include <NameRegistry.h>
  114. #include <DriverServices.h>
  115. #endif
  116.  
  117. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  118.  * Public definitions for the LogLibrary.
  119.  *
  120.  * We can store kLogEntryDataSize longwords in each entry. This is the maximum
  121.  * that we can store, given 3 bits per format value.
  122.  */
  123. #define kLogEntryDataSize        10
  124. /*
  125.  * Boolean32 is a Boolean stored in a longword. This prevents Think vs. MPW
  126.  * variable confusion.
  127.  */
  128. typedef UInt32                    Boolean32;
  129. /*
  130.  * The log record name is actually a property in the System Name Registry.
  131.  * Applications can treat this as a (short) C string.
  132.  */
  133. typedef RegPropertyNameBuf    LogRecordNameBuf;
  134. typedef RegPropertyNamePtr    LogRecordNamePtr;
  135. /*
  136.  * Each log record entry contains the following information:
  137.  *        eventTime        The system UpTime value at the time the data was collected.
  138.  *        sequence        The ordinal index of this entry. This will always increment.
  139.  *                        (If you log one entry per microsecond, it will wrap around
  140.  *                        after about 70 minutes).
  141.  *        idCode            A longword that uniquely identifies the log entry (i.e.,
  142.  *                        who logged it). This is provided by the WriteLogEntry caller.
  143.  *        format            A longword that describes the format of the log data.
  144.  *        data[10]        Ten longwords that contain the entry-unique information.
  145.  *                        The actual count is defined by the format longword.
  146.  * upTime and sequence are maintained by LogLibrary routines, while the other
  147.  * parameters are copied from the WriteLogEntry parameters.
  148.  */
  149. #if defined(powerc) || defined(__powerc)
  150. #pragma option align=mac68K
  151. #endif
  152. struct LogEntryRecord {
  153.     AbsoluteTime        eventTime;        /* UpTime() at SaveLogEntry call            */
  154.     UInt32                sequence;        /* Entry number (monotomically increasing)    */
  155.     OSType                idCode;            /* Why are we logging -- set by caller        */
  156.     UInt32                format;            /* Format of the data (see below)            */
  157.     UInt32                data[kLogEntryDataSize];    /* The data itself                */
  158. };
  159. #if defined(powerc) || defined(__powerc)
  160. #pragma options align=reset
  161. #endif
  162. typedef struct LogEntryRecord LogEntryRecord, *LogEntryPtr;
  163. /*
  164.  * These flags control data formatting. Note: because data is passed using
  165.  * variable-length argument list conventions and we want the code to work
  166.  * compatably on both Think and MPW, all numeric parameters must be passed as
  167.  * "long" or "unsigned long." For example, to pass an OSErr code, do
  168.  *        WriteLogEntry(
  169.  *            'fubr',
  170.  *            LogFormat1(kLogFormatSigned),
  171.  *            (signed long) statusCode
  172.  *        );
  173.  */
  174. enum {
  175.     /*
  176.      * Parameters to the LogFormat macro.
  177.      */
  178.     kLogFormatSigned            = 0,        /* Signed long                            */
  179.     kLogFormatUnsigned            = 1,        /* Unsigned (decimal)                    */
  180.     kLogFormatHex                = 2,        /* Unsigned (hex + 'char')                */
  181.     kLogFormatAddress            = 3,        /* Unsigned hex only                    */
  182.     kLogFormatReserved4            = 4,        /* Unused                                */
  183.     kLogFormatReserved5            = 5,        /* Unused                                */
  184.     kLogFormatString            = 6,        /* String (last format)                    */
  185.     kLogFormatEnd                = 7,        /* End signal (no data)                    */
  186.     /*
  187.      * kLogFormatShift must be large enough to shift all format codes. All data
  188.      * format codes must fit into a single longword.
  189.      */
  190.     kLogFormatShift                = 3,
  191.     kLogFormatMask                = (1 << kLogFormatShift) - 1
  192. };
  193. #if ((kLogFormatShift * kLogEntryDataSize) > 32)
  194.     << (kLogFormatShift * kLogEntryDataSize) must be <= 32 bits (longword size) >>
  195. #endif
  196.  
  197. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  198.  * This section should be regarded as "private" to the LogLibrary. Applications
  199.  * that use the library never need to reference (or dereference) these structures.
  200.  * Although the content of the structures is shown explicitly, applications should
  201.  * treat these structures as "opaque" and "subject to change without notice" in
  202.  * future Macintosh operating system releases.
  203.  *
  204.  * LogRecords are stored in system resident memory (roughly equivalent to the System
  205.  * Heap in System 7.5. A named pointer to each LogRecord is stored in the System
  206.  * Registry as a property to the LogRegistryEntry name ("LogLibrary.N"). The entry name
  207.  * will change with incompatible changes to the entry format. Because the log library
  208.  * manager must be in Power PC native code, 68000 routines access the functions through
  209.  * a "glue" library that calls the functions in a shared library.
  210.  */
  211. #define kLogSharedLibraryName    "\pLogLibrary"
  212. #define kLogRegistryEntry        ":LogLibrary.1"
  213. /*
  214.  * The LogRecord iterator combines an entry identifier and a property iterator.
  215.  */
  216. #if defined(powerc) || defined(__powerc)
  217. #pragma option align=mac68K
  218. #endif
  219. struct LogRecordIter {
  220.     RegPropertyIter        propertyIterCookie;
  221. };
  222. #if defined(powerc) || defined(__powerc)
  223. #pragma options align=reset
  224. #endif
  225. typedef struct LogRecordIter LogRecordIter, *LogRecordIterPtr;
  226.  
  227. #if defined(powerc) || defined(__powerc)
  228. #pragma option align=mac68K
  229. #endif
  230. struct LogRecord {
  231.     volatile UInt32        semaphore;            /* In critical section if non-zero        */
  232.     volatile UInt32        lostLockCounter;    /* Can't enter critical section            */
  233.     volatile UInt32        sequenceCounter;    /* Absolute sequence counter            */
  234.     volatile UInt32        flags;                /* Logging & lost data flags            */
  235.     LogRecordNameBuf    logName;            /* A redundant copy of the log's name    */
  236.     volatile UInt32        entryPutIndex;        /* Where to store the next record        */
  237.     volatile UInt32        entryGetIndex;        /* Where to retrieve the next record    */
  238.     volatile UInt32        entryMaxIndex;        /* Actual number of log entries            */
  239.     LogEntryRecord        entries[1];            /* Log entries are stored here            */
  240. };
  241. #if defined(powerc) || defined(__powerc)
  242. #pragma options align=reset
  243. #endif
  244. typedef struct LogRecord LogRecord, *LogRecordPtr;
  245. /*
  246.  * Values for the flags variable in the LogDataRecord. These are private to the
  247.  * LogData library and dcmd display routine.
  248.  */
  249. enum {
  250.     kLogDataEnabledMask            = (1L <<  0),
  251.     kLogDataPreserveFirstMask    = (1L <<  1),
  252.     kLogDataWrapAroundMask        = (1L <<  2)
  253. };
  254.  
  255. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  256.  * The following information is public.
  257.  *
  258.  * The LogFormat macro stores the format word.
  259.  */
  260. #define LogFormat(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9)    \
  261.     (  (f0)                                            \
  262.      | ((f1) << (kLogFormatShift * 1))                \
  263.      | ((f2) << (kLogFormatShift * 2))                \
  264.      | ((f3) << (kLogFormatShift * 3))                \
  265.      | ((f4) << (kLogFormatShift * 4))                \
  266.      | ((f5) << (kLogFormatShift * 5))                \
  267.      | ((f6) << (kLogFormatShift * 6))                \
  268.      | ((f7) << (kLogFormatShift * 7))                \
  269.      | ((f8) << (kLogFormatShift * 8))                \
  270.      | ((f9) << (kLogFormatShift * 9))                \
  271.     )
  272. #define LogFormat1(f0)                                                            \
  273.     LogFormat(                                                                    \
  274.         (f0),          kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  275.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  276.         kLogFormatEnd, kLogFormatEnd                                            \
  277.     )
  278. #define LogFormat2(f0, f1)                                                        \
  279.     LogFormat(                                                                    \
  280.         (f0),          (f1),          kLogFormatEnd, kLogFormatEnd,                \
  281.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  282.         kLogFormatEnd, kLogFormatEnd                                            \
  283.     )
  284. #define LogFormat3(f0, f1, f2)                                                    \
  285.     LogFormat(                                                                    \
  286.         (f0),          (f1),          (f2),          kLogFormatEnd,                \
  287.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  288.         kLogFormatEnd, kLogFormatEnd                                            \
  289.     )
  290. #define LogFormat4(f0, f1, f2, f3)                                                \
  291.     LogFormat(                                                                    \
  292.         (f0),          (f1),          (f2),          (f3),                        \
  293.         kLogFormatEnd, kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,                \
  294.         kLogFormatEnd, kLogFormatEnd                                            \
  295.     )
  296. #define LogFormat5(f0, f1, f2, f3, f4)                                            \
  297.     LogFormat(                                                                    \
  298.         (f0),          (f1),          (f2),          (f3),                        \
  299.         (f4),            kLogFormatEnd, kLogFormatEnd, kLogFormatEnd,            \
  300.         kLogFormatEnd, kLogFormatEnd                                            \
  301.     )
  302. #define LogFormat6(f0, f1, f2, f3, f4, f5)                                        \
  303.     LogFormat(                                                                    \
  304.         (f0),          (f1),          (f2),          (f3),                        \
  305.         (f4),          (f5),          kLogFormatEnd, kLogFormatEnd,                \
  306.         kLogFormatEnd, kLogFormatEnd                                            \
  307.     )
  308. #define LogFormat7(f0, f1, f2, f3, f4, f5, f6)                                    \
  309.     LogFormat(                                                                    \
  310.         (f0),          (f1),          (f2),          (f3),                        \
  311.         (f4),          (f5),          (f6),          kLogFormatEnd,                \
  312.         kLogFormatEnd, kLogFormatEnd                                            \
  313.     )
  314. #define LogFormat8(f0, f1, f2, f3, f4, f5, f6, f7)                                \
  315.     LogFormat(                                                                    \
  316.         (f0),          (f1),          (f2),          (f3),                        \
  317.         (f4),          (f5),          (f6),          (f7),                        \
  318.         kLogFormatEnd, kLogFormatEnd                                            \
  319.     )
  320. #define LogFormat9(f0, f1, f2, f3, f4, f5, f6, f7, f8)                            \
  321.     LogFormat(                                                                    \
  322.         (f0),          (f1),          (f2),          (f3),                        \
  323.         (f4),          (f5),          (f6),          (f7),                        \
  324.         (f8),          kLogFormatEnd                                            \
  325.     )
  326. #define LogFormat10(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9)                        \
  327.     LogFormat(                                                                    \
  328.         (f0),          (f1),          (f2),          (f3),                        \
  329.         (f4),          (f5),          (f6),          (f7),                        \
  330.         (f8),          (f9)                                                        \
  331.     )
  332. /*
  333.  * These are popular format types.
  334.  */
  335. #define LogStringFormat    LogFormat1(kLogFormatString)
  336. #define LogStatusFormat    LogFormat2(kLogFormatSigned, kLogFormatString)
  337.  
  338. /*
  339.  * The application or code segment calls the following functions to access LogRecord 
  340.  * records MakeLogRecord must be called from a non-interrupt execution level as it may
  341.  * allocate memory and store information into the System Name Registry. MakeLogRecord
  342.  * or GetLogRecordPtr must be called before calling any other LogRecord function. 
  343.  *
  344.  * GetLogRecordPtr can generally be called either from noninterrupt or secondary
  345.  * execution level, however the first call from a 68000 architecture module must be
  346.  * able to load a shared library and, potentially, allocate memory.
  347.  *
  348.  * All other routines may be called from any execution level.
  349.  */
  350.  
  351. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  352.  * MakeLogRecord
  353.  *
  354.  * The first time this function is called after the system is started, it creates a
  355.  * log record for this name. The log is initially enabled, and deletes overflow at the
  356.  * start. It thus retains the *end* of the log -- this is useful for ongoing logging,
  357.  * but may lose the start of a disaster sequence (as it records the flow of errors
  358.  * through the system, rather than the intial cause.
  359.  *
  360.  * LogRecordNamePtr must define a non-null string. nEntries must be non-zero.
  361.  * The logRecordNamePtr "name" is reserved to the Name Registry. Don't use it.
  362.  *
  363.  * This function must be called in a context that can allocate memory. The first
  364.  * call from a 68000 architecture module must be able to load a shared library.
  365.  *
  366.  * Return the LogRecordPtr for this log, or NULL if unsuccessful.
  367.  */
  368. pascal LogRecordPtr            MakeLogRecord(
  369.         const LogRecordNamePtr    logRecordNamePtr,        /* Log name (C-string)        */
  370.         UInt32                    nEntries                /* Number of Log entries    */
  371.     );
  372.  
  373. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  374.  * GetLogRecordPtr
  375.  *
  376.  * Return a pointer to the log record for a specified name. Returns NULL if it was
  377.  * not found (WriteLogEntry, etc. will not choke).
  378.  */
  379. pascal LogRecordPtr            GetLogRecordPtr(
  380.         const LogRecordNamePtr    logRecordNamePtr        /* Log name (C-string)        */
  381.     );
  382.  
  383. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  384.  * LogString
  385.  *
  386.  * LogString calls WriteLogEntry with a single Pascal string argument. Following ANSI
  387.  * C conventions, it is provided as a macro and as a function. The function may be
  388.  * called from Pascal.
  389.  */
  390. #define LogString(ptr, idCode, string) \
  391.         WriteLogEntry((ptr), (idCode), LogStringFormat, string)
  392. pascal OSErr                (LogString)(
  393.         LogRecordPtr            logRecordPtr,            /* This log record            */
  394.         OSType                    idCode,                    /* Entry identifier            */
  395.         ConstStr255Param        string                    /* The datum                */
  396.     );
  397.  
  398. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  399.  * LogStatusString
  400.  *
  401.  * LogStatusString calls WriteLogEntry with the status and string values. It is
  402.  * provided as a macro and as a function.
  403.  */
  404. #define LogStatusString(ptr, idCode, status, string) (    \
  405.         WriteLogEntry(                                    \
  406.             (ptr),                                        \
  407.             (idCode),                                    \
  408.             LogStatusFormat,                            \
  409.             (signed long) (status),                        \
  410.             string                                        \
  411.         )                                                \
  412.     )
  413. pascal OSErr                (LogStatusString)(
  414.         LogRecordPtr            logRecordPtr,            /* This log record            */
  415.         OSType                    idCode,                    /* Entry identifier            */
  416.         OSErr                    status,                    /* Status error code        */
  417.         ConstStr255Param        string                    /* The datum                */
  418.     );
  419.  
  420. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  421.  * WriteLogEntry
  422.  *
  423.  * Write a LogRecord entry if logging is enabled and there is space in the log.
  424.  *    logRecordPtr Identifies this log.
  425.  *    idCode        A user-controlled value, by convention an OSType (4-byte character)
  426.  *                that identifies this entry. The display application prints it. Note
  427.  *                that, on the Macintosh, an OSType can be coerced from/to any longword
  428.  *                scalar (such as an address) without loss of data. This may be useful
  429.  *                for user-written display applications.
  430.  *    format        A longword that specifies the format of the remaining data. Use the
  431.  *                value LogStringFormat if the only datum is a Pascal string; use the
  432.  *                value LogStatusFormat if you are logging an OSErr and an accompaning
  433.  *                string; otherwise, use the LogFormat macro to create the value.
  434.  *    ...            Additional data as needed. Note that all data must be specified as, or
  435.  *                coerced to longwords (StringPtr, address, or long). Naturally short
  436.  *                integers such as Booleans or OSErr codes must be explicitly cast to
  437.  *                long. This is needed because of compiler options regarding data
  438.  *                format lengths.
  439.  * WriteLogData will always be in the current instruction architecture as you cannot
  440.  * make a MixedMode call with a variable-length argument list. Also, WriteLogData
  441.  * cannot be called from Pascal for the same reason.
  442.  *
  443.  * Return values:
  444.  *    noErr        Normal completion or logging was disabled.
  445.  *    writErr        The entry could not be stored because the LogRecord was full. This
  446.  *                can usually be ignored.
  447.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  448.  *                locked -- presumably by an asynchronous process. The caller may
  449.  *                wish to try the operation again, perhaps after a short delay.
  450.  */
  451. OSErr                        WriteLogEntry(
  452.         LogRecordPtr            logRecordPtr,            /* This log record            */
  453.         OSType                    idCode,                    /* Entry identifier            */
  454.         UInt32                    format,                    /* Format bits                */
  455.         ...                                                /* Additional data, if any    */
  456.     );
  457.  
  458. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  459.  * StoreLogEntry
  460.  *
  461.  * Store a formatted LogEntryRecord in the log. This is the only routine that
  462.  * writes the log entry. Normally, it is only called by WriteLogData. This function
  463.  * will store the following data into the caller's LogEntryRecord (even if logging
  464.  * was disabled or the log was full):
  465.  *        sequence    This entry sequence counter.
  466.  *        eventTime    UpTime when this record was added to the LogRecord.
  467.  *
  468.  * Return values:
  469.  *    noErr        Normal completion or logging was disabled.
  470.  *    writErr        The entry could not be stored because the LogRecord was full. This
  471.  *                can usually be ignored.
  472.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  473.  *                locked -- presumably by an asynchronous process. The caller may
  474.  *                wish to try the operation again, perhaps after a short delay.
  475.  */
  476. pascal OSErr                StoreLogEntry(
  477.         LogRecordPtr            logRecordPtr,            /* This log record            */
  478.         const LogEntryPtr        logEntryPtr                /* Gets this entry            */
  479.     );
  480.  
  481. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  482.  * ReadLogEntry
  483.  *
  484.  * Read the next LogRecord entry. This returns a copy of the entry, if one is
  485.  * available. ReadLogEntry also returns the UpTime value when it was called. This
  486.  * is needed by 68000-based applications as the function is only available from the
  487.  * Power PC native DriverServices library.
  488.  *
  489.  * Return values:
  490.  *    noErr        Normal completion or logging was disabled.
  491.  *    readErr        The entry could not be stored because the LogRecord was empty
  492.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  493.  *                locked -- presumably by an asynchronous process. The caller may
  494.  *                wish to try the operation again, perhaps after a short delay.
  495.  */
  496. pascal OSErr                ReadLogEntry(
  497.         LogRecordPtr            logRecordPtr,            /* This log record            */
  498.         LogEntryPtr                thisLogEntry            /* Store entry here            */
  499.     );
  500.  
  501. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  502.  * EnableLogRecord
  503.  *
  504.  * Enable/disable logging. Returns the old logging state.
  505.  */
  506. pascal Boolean32            EnableLogRecord(
  507.         LogRecordPtr            logRecordPtr,            /* This log record            */
  508.         Boolean32                enableLogging            /* TRUE to enable logging    */
  509.     );
  510.  
  511. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  512.  * PreserveLogRecord
  513.  *
  514.  * Set the preserveFirst flag. Returns the old flag value. 
  515.  */
  516. pascal Boolean32            PreserveLogRecord(
  517.         LogRecordPtr            logRecordPtr,            /* This log record            */
  518.         Boolean32                preserveFirst            /* TRUE to preserve start    */
  519.     );
  520.  
  521. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  522.  * GetLogSemaphoreLostCounter
  523.  *
  524.  * Because the log library uses a "lossy" algorithm to maintain exclusive access to
  525.  * the critical section, there is a very slight possibility that two processes will
  526.  * try to access the log record at the same time. In this case, ReadLogEntry will
  527.  * stall (loop) and eventually succeed, while WriteLogEntry will lose the datum, and
  528.  * increment the logLostCounter.
  529.  */
  530. pascal UInt32                GetLogSemaphoreLostCounter(
  531.         LogRecordPtr            logRecordPtr            /* This log record            */
  532.     );
  533.  
  534. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  535.  * FormatLogEntryData
  536.  *
  537.  * This function is in LogFormat.c - it formats an entry into a single line
  538.  * that is stored in the result. Note: only the data is formatted: the timestamp
  539.  * is not processed. This function may be called from a non-application context;
  540.  * It does not require a MixedMode switch.
  541.  */
  542. pascal void                    FormatLogEntryData(
  543.         const LogEntryPtr        thisLogEntry,            /* Format this entry        */
  544.         StringPtr                result
  545.     );
  546.  
  547. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  548.  * LogConvertTimestamp
  549.  *
  550.  * This function is in LogConvertTimestamp.c - it formats the timestamp into civil
  551.  * ("clock") time, returning the result in a DateTimeRec and an associated residual
  552.  * number of nanoseconds. This routine calls Macintosh Toolbox services. It is not
  553.  * in the shared library. Calling sequence:
  554.  *        LogEntryRecord        thisLogEntry;
  555.  *        UInt32                thisCivilTime;
  556.  *        DateTimeRec            thisDateTime;
  557.  *        UInt32                residualNanoseconds;
  558.  *
  559.  *        if (ReadLogEntry(myLogRecordPtr, &thisLogEntry)) {
  560.  *            LogConvertTimestamp(
  561.  *                &thisLogEntry,
  562.  *                &thisDateTime,
  563.  *                &residualNanoseconds
  564.  *            );
  565.  *        }
  566.  * thisCivilTime will have the civil time (seconds since 1904) when the entry was
  567.  * stored into the log. thisDateTime will have the corresponding civil date
  568.  * (Year, Month, Day, Hour, Minute, Second)
  569.  */
  570. pascal void                    LogConvertTimestamp(
  571.         LogEntryPtr                logEntryPtr,            /* Current log entry        */
  572.         DateTimeRec                *eventDateTime,            /* Year, Month, Day etc.    */
  573.         UInt32                    *residualNanoseconds    /* Fractional second        */
  574.     );
  575.  
  576. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  577.  * FormatLogEntryTimestamp
  578.  *
  579.  * Format a converted log entry timestamp (prepared by ConvertLogEntryTimestamp). The
  580.  * result is appended to result as a fixed-length string: "yyyy.mm.dd hh.mm.ss.msec"
  581.  * FormatLogEntryTimestamp does not use the system date formatting routines. Note
  582.  * that the fractional seconds are truncated to the nearest lower millisecond, even
  583.  * though nanosecond precision is potentially available. This function does not
  584.  * require a MixedMode switch.
  585.  */
  586. pascal void                    FormatLogEntryTimestamp(
  587.         StringPtr                result,                    /* Append to this string    */
  588.         const DateTimeRec        *eventDateTime,            /* Year, Month, Day etc.    */
  589.         UInt32                    residualNanoseconds        /* Fractional second        */
  590.     );
  591.  
  592. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  593.  * LogRecord utilities.
  594.  *
  595.  * These three functions are used to locate all registered log records. They may be
  596.  * used for a display utility or MacsBug dcmd. Applications call them as follows:
  597.  *
  598.  *    LogRecordIter            cookie;
  599.  *
  600.  *    if (LogRecordIterateCreate(&cookie) == noErr) {
  601.  *        while ((logRecordPtr = LogRecordIterate(&cookie)) != NULL) {
  602.  *            ... Process this LogRecord, the name may be extracted from the record ...
  603.  *        }
  604.  *        LogRecordIterateDispose(&cookie);
  605.  *    }
  606.  */
  607. pascal OSErr                LogRecordIterateCreate(
  608.         LogRecordIterPtr        cookie
  609.     );
  610. pascal LogRecordPtr            LogRecordIterate(
  611.         LogRecordIterPtr        cookie
  612.     );
  613. pascal void                    LogRecordIterateDispose(
  614.         LogRecordIterPtr        cookie
  615.     );
  616.  
  617. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  618.  * CopyLogRecord
  619.  *
  620.  * This function copies the permanent part of the LogRecord (srcLogRecordPtr) to a
  621.  * caller-designated area (dstLogRecordPtr). It is only for the benefit of the DCMD.
  622.  * It returns noErr if successful, paramErr if either the source or destination parameters
  623.  * are incorrect, or a Shared Library Manager error. This function ignores the interlock
  624.  * semaphore. Thus, it may return inconstent data. It does not copy the first LogRecordEntry.
  625.  *
  626.  * Only the DCMD is permitted to call this function!
  627.  */
  628. pascal OSErr                CopyLogRecordInfo(
  629.         const LogRecordPtr        srcLogRecordPtr,
  630.         LogRecordPtr            dstLogRecordPtr
  631.     );
  632.  
  633. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  634.  * CopyLogEntry
  635.  *
  636.  * Copy the specified LogRecord entry. This returns a copy of the entry. It is only
  637.  * used by the DCMD to snapshot a LogRecord.
  638.  *
  639.  * Return values:
  640.  *    noErr        Normal completion or logging was disabled.
  641.  *    readErr        The entry could not be stored because the LogRecord was empty.
  642.  *    fBsyErr        The entry could not be stored because the LogRecord semaphore was
  643.  *                locked -- presumably by an asynchronous process. The caller may
  644.  *                wish to try the operation again, perhaps after a short delay.
  645.  */
  646. pascal OSErr                CopyLogEntry(
  647.         LogRecordPtr            logRecordPtr,            /* This log record            */
  648.         UInt32                    getIndex,                /* This entry index            */
  649.         LogEntryPtr                thisLogEntry            /* Store entry here            */
  650.     );
  651.  
  652. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  653.  * LogLibraryUpTime
  654.  *
  655.  * This provides UpTime to a caller running 68000 for the benefit of the dcmd.
  656.  * The value is returned in nanoseconds for convenience.
  657.  */
  658. pascal void                    LogLibraryUpTime(
  659.         Nanoseconds                *resultPtr
  660.     );
  661.  
  662. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  663.  * LogLibraryAbsoluteToNanoseconds
  664.  *
  665.  * This converts an UpTime value to nanoseconds.
  666.  */
  667. pascal void                    LogLibraryAbsoluteToNanoseconds(
  668.         const AbsoluteTime        *sourcePtr,
  669.         Nanoseconds                *resultPtr
  670.     );
  671.  
  672. #endif    /* __LogLibrary__    */
  673.  
  674.